package com.pinguix.games.pong;

import java.util.Random;

import danger.ui.Pen;
import danger.ui.Point;
import danger.ui.Rect;
import danger.util.DEBUG;

public class Ball extends Object2D
{
	public static final int HEIGHT = 5;
	public static final int WIDTH = 5;
	public static final int DSPEED = 15;
	public static final int DRESETTIME = 20;
	
	private int _currSpeed = DSPEED;
	private double _direction = Math.PI/4;
	private boolean _deadBall = false;
	
	private Rect _stageBounds;
	private PongWindow _playField;
	
	private int _resetTime = DRESETTIME;
	private Random _rand = new Random();

	public Ball(Point position, PongWindow window)
	{
		this._bounds = new Rect(position.h, position.v, position.h + WIDTH, position.v + HEIGHT);
		_velocity = new Point(0,0);
		_playField = window;
		_stageBounds = _playField.getBounds();
		reset();
	}
	
	//Returns travel angle in rads
	public double getVelocityAngle()
	{
		return Math.atan((double)(_velocity.v)/_velocity.h);
	}
	public double getDirection()
	{
		return getVelocityAngle();
	}
	
	public double getVelocityMagnitude()
	{
		return Math.sqrt(Math.pow(_velocity.v, 2) + Math.pow(_velocity.h, 2));
	}
	public int getSpeed()
	{
		return (int)(getVelocityMagnitude() + .5);
	}
	
	public void paint(Pen pen)
	{
		pen.fillOval(_bounds);
	}
	
	public void update()
	{
		if(_resetTime > 0)
		{
			_resetTime--;
		}
		else if(_resetTime == 0)
		{
			setVelocity();
			_resetTime--;
		}
		
		displace(_velocity.v, _velocity.h);
		
		if(offScreenLeft())
			_playField.addPointRight();
		else if(offScreenRight())
			_playField.addPointLeft();
	}
	
	public void reset()
	{
		_deadBall = false;
		moveTo(new Point(_stageBounds.getWidth()/2, _stageBounds.getHeight()/2));
		setSpeed(0);
		_resetTime = DRESETTIME; 
	}
	
	public void setSpeed(int speed)
	{
		int hDir = (int)(Math.signum(_velocity.h));
		int vDir = (int)(Math.signum(_velocity.v));
		
		_velocity.h = (int)(Math.abs((double)(speed)*Math.cos(getVelocityAngle()))) * hDir;
		_velocity.v = (int)(Math.abs((double)(speed)*Math.sin(getVelocityAngle()))) * vDir;
	}
	
	public Point getVelocity()
	{
		return(_velocity);
	}
	public void setVelocity()
	{
		if(_rand.nextBoolean())
			setVelocity(_currSpeed, _direction);
		else
			setVelocity(-_currSpeed, _direction);
	}
	public void setVelocity(Point vel)
	{
		_velocity.h = vel.h;
		_velocity.v = vel.v;
	}
	public void setVelocity(int speed, double direction)
	{
		_velocity.h = (int)(speed*Math.cos(direction));
		_velocity.v = (int)(speed*Math.sin(direction));
	}
	
	public void kill()
	{
		_deadBall = true;
	}
	public boolean isDead()
	{
		return _deadBall;
	}
	
	public Rect getBounds()
	{
		return this._bounds;
	}
	
	public void displace(int dispV, int dispH)
	{
		_bounds.top += dispV;
		_bounds.bottom += dispV;
		_bounds.left += dispH;
		_bounds.right += dispH;
	}
	public void moveTo(Point pt)
	{
		int height = _bounds.getHeight();
		int width = _bounds.getWidth();
		_bounds.top = pt.v;
		_bounds.left = pt.h;
		_bounds.bottom = _bounds.top + height;
		_bounds.right = _bounds.left + width;
	}
	
	private boolean offScreenLeft()
	{
		if(_bounds.right <= _stageBounds.left)
			return true;
		return false;
	}
	private boolean offScreenRight()
	{
		if(_bounds.left >= _stageBounds.right)
			return true;
		return false;
	}
}
